package org.study.lambda;

import lombok.*;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2024年11月28日
 */
public class LambdaDistinctTests {
    public static void main(String[] args) {
        stringRemoveDuplication();
        listRemoveDuplication1();
        listRemoveDuplication2();
        listRemoveDuplication3();
        listRemoveDuplication4();
    }

    public static void stringRemoveDuplication() {
        System.out.println("\n========== 测试 stringRemoveDuplication() 方法：");
        // 去除重复的string
        List<String> strList = new ArrayList<>() {{
            this.add("aa");
            this.add("aa");
            this.add("bb");
            this.add("cc");
        }};
        strList = strList.stream().distinct().collect(Collectors.toList());
        for (String str : strList) {
            System.out.println(str);
        }
    }

    public static void listRemoveDuplication1() {
        System.out.println("\n========== 测试 listRemoveDuplication1() 方法：");
        // 根据对象中属性去重
        List<User> userList = new ArrayList<>() {{
            this.add(new User(1L, "aa", "aa"));
            this.add(new User(1L, "aa", "bb"));
            this.add(new User(1L, "aa", "cc"));
        }};
        userList = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getId))), ArrayList::new));
        for (User user : userList) {
            System.out.println(user);
        }
    }

    public static void listRemoveDuplication2() {
        System.out.println("\n========== 测试 listRemoveDuplication2() 方法：");
        // 根据属性id和username去重，满足id和pwd都一致时，视为相同属性
        List<User> userList = new ArrayList<>() {{
            this.add(new User(1L, "aa", "aa"));
            this.add(new User(1L, "aa", "bb"));
            this.add(new User(1L, "bb", "aa"));
            this.add(new User(1L, "cc", "aa"));
            this.add(new User(1L, "cc", "bb"));
            this.add(new User(1L, "cc", "cc"));
        }};
        userList = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getId() + ";" + o.getUsername()))), ArrayList::new));
        for (User user : userList) {
            System.out.println(user);
        }
    }

    public static void listRemoveDuplication3() {
        System.out.println("\n========== 测试 listRemoveDuplication3() 方法：");
        List<User> userList = new ArrayList<>() {{
            this.add(new User(1L, "aa", "aa"));
            this.add(new User(1L, "aa", "bb"));
            this.add(new User(1L, "bb", "aa"));
            this.add(new User(1L, "cc", "aa"));
            this.add(new User(1L, "cc", "bb"));
            this.add(new User(1L, "cc", "cc"));
        }};
        Map<String, User> result = userList.stream()
                .collect(Collectors.toMap(
                        o -> o.getId() + o.getUsername(), // key generator
                        Function.identity(), // value mapper
                        (oldValue, newValue) -> oldValue // merge function
                ));
        List<User> distinctUserList = new ArrayList<>(result.values());
        for (User user : distinctUserList) {
            System.out.println(user);
        }
    }

    public static void listRemoveDuplication4() {
        System.out.println("\n========== 测试 listRemoveDuplication4() 方法：");
        List<User> userList = new ArrayList<>() {{
            this.add(new User(1L, "aa", "aa"));
            this.add(new User(1L, "aa", "bb"));
            this.add(new User(1L, "bb", "aa"));
            this.add(new User(1L, "cc", "aa"));
            this.add(new User(1L, "cc", "bb"));
            this.add(new User(1L, "cc", "cc"));
        }};
        Map<String, Long> nameCountMap = userList.stream().collect(Collectors.groupingBy(user -> user.getId() + ":" + user.getUsername(), Collectors.counting()));
        nameCountMap.forEach((name, count) -> System.out.println(name + ": " + count));
    }

    @Data
    @ToString
    @EqualsAndHashCode
    @NoArgsConstructor
    @AllArgsConstructor
    static class User implements Serializable {
        private static final long serialVersionUID = 1L;

        private Long id;
        private String username;
        private String password;
    }
}
